package com.stroke.tools.animation;

import com.stroke.util.IOHelper;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.log4j.Logger;

import javax.imageio.ImageIO;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Author: Igor Bubelov
 * Date: 3/11/11 11:26 PM
 */
public class AnimationFile {
    private File file;
    private boolean opened;
    private List<Frame> frames = new ArrayList<Frame>();

    public AnimationFile(File file) {
        this.file = file;
    }

    public AnimationFile(String path) {
        this(new File(path));
    }

    public void open() {
        if (!opened) {
            File tempRoot = new File(file.getAbsolutePath().replace(file.getName(), "") + "~" + file.getName());

            tempRoot.mkdir();

            try {
                ZipFile zipFile = new ZipFile(file);
                Enumeration entries = zipFile.entries();

                while (entries.hasMoreElements()) {
                    ZipEntry entry = (ZipEntry) entries.nextElement();
                    InputStream inputStream = zipFile.getInputStream(entry);
                    OutputStream outputStream = new FileOutputStream(tempRoot.getAbsolutePath() + File.separator + entry.getName());
                    IOHelper.copyInputStream(inputStream, outputStream);
                }
            } catch (Exception ex) {
                Logger.getLogger(getClass()).error("Failed to open an animation: " + file.getName(), ex);
            }

            Map<Integer, String> description = loadDescription(new File(tempRoot.getAbsolutePath() + File.separator + "description.xml"));

            for (Integer key : description.keySet()) {
                File file = new File(tempRoot.getAbsolutePath() + File.separator + description.get(key));
                frames.add(new Frame(file, key));
            }

            opened = true;
        } else {
            Logger.getLogger(getClass()).error("Trying to open the animation already opened");
        }
    }

    public void close() {
        if (opened) {
            File tempRoot = new File(file.getAbsolutePath().replace(file.getName(), "") + "~" + file.getName());

            for (File file : tempRoot.listFiles()) {
                file.delete();
            }

            tempRoot.delete();

            frames.clear();

            opened = false;
        } else {
            Logger.getLogger(getClass()).error("Trying to close the animation already closed");
        }
    }

    private Map<Integer, String> loadDescription(File description) {
        Map<Integer, String> result = new HashMap<Integer, String>();

        try {
            BufferedReader reader = new BufferedReader(new FileReader(description));

            String line;

            while ((line = reader.readLine()) != null) {
                if (!line.contains("<frame")) {
                    continue;
                }

                line = line.replace("<frame number=\"", "");
                line = line.replace("\" file=\"", " ");
                line = line.replace("\"/>", "");

                Scanner scanner = new Scanner(line);

                int number = scanner.nextInt();
                String fileName = scanner.next();

                result.put(number, fileName);
            }

            reader.close();
        } catch (Exception ex) {
            Logger.getLogger(getClass()).error("Failed to load the animation description: " + file.getName(), ex);
        }

        return result;
    }

    public List<Frame> getFramesSorted() {
        Collections.sort(frames, new FramePositionComparator());
        return frames;
    }
}